library flamingtext;

import 'dart:typed_data';                                                                                                                                                                     
import 'dart:html';
import 'dart:math';
import 'package:web_ui/web_ui.dart';
import 'Color.dart';

/**
 * Generate and manipulate an HTML5 canvas to simulate burning text.
 * Use bi-directional binding to allow the user to specify text to burn.
 * Create multiple color maps for users to play with.
 */

class flamingText {
  // Data binding elements
  String text;                                // Data binding element for display text
  int coolingRate;                            // Cooling rate for pixels
  Random rng;                                 // Random number generator
  
  // Canvas elements
  CanvasElement canvas;                       // The actual canvas element
  CanvasRenderingContext2D context;           // The drawing context for the canvas.
  ImageData pixels;                           // A representation of the image's data in pixel form
  int rowLength;                              // Store the number of elements (rgba) in a row
  
  flamingText(this.canvas) {
    text = "";
    coolingRate = 5;
    initCanvas();
    initImageData();
    rng = new Random();
  }
  
  /**
   * Initialize Canvas elements
   */
  void initCanvas() {    
    // Set up the context, draw a black screen, and set that as the starting image data 
    context = canvas.getContext("2d");
    context.setStrokeColorRgb(0, 0, 0, 255);
    context.fillRect(0, 0, canvas.width, canvas.height);
    pixels = context.getImageDataHD(0, 0, canvas.width, canvas.height);
    rowLength = pixels.width * 4;
  }
  
  void initImageData() {
    
  }
  
  /**
   * Draw a line of pixels at the bottom of the screen to seed the flames.
   */
  void seedFlames() {
    // Find the first element of the last row
    int lastRow = (pixels.data.length - rowLength).floor();
    
    for (int i = 4; i < rowLength - 4; i += 8) {
      pixels.data[i+lastRow] = rng.nextInt(255);
      pixels.data[i+lastRow+1] = rng.nextInt(255);
      pixels.data[i+lastRow+2] = rng.nextInt(255);
    }
    
    context.putImageDataHD(pixels, 0, 0);
  }
    
  /**
   * Main animation loop for the program.
   */
  void render() {
    // Canvas starts off prepped for first pass before render is called.
    // We can start right off with moving everything upwards and cooling.
    // First, Seed the flames at the bottom of the context
    seedFlames();
    
    // TODO: draw text onto the screen.
    
    // Move through each row, get the color data for the pixels below, and cool.
    for (int i = pixels.data.length - (rowLength * 2); 
        i > 0; 
        i -= rowLength) {
      // move through the current row's pixels, and compare them with the surrounding pixels.
      for (int x = 4; x < rowLength - 4; x += 4) {
        // get the current offset from 0
        int offset = i + x;
        for (int y = 0; y < 3; y++) {
          int color = ((pixels.data[offset+rowLength+y]
            + pixels.data[offset+rowLength+4+y]
            + pixels.data[offset+rowLength-4+y]) / 3).floor();
          pixels.data[offset+y] = max(0, color - rng.nextInt(coolingRate));
        }
      }
    }
    
    context.putImageDataHD(pixels, 0, 0);
    
    window.animationFrame.then((time) => render());
  }
}

flamingText flame;

void main() {
  flame = new flamingText(query('#flamingtext'));
  flame.render();
}